{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.model_selection import train_test_split"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Sex</th>\n",
       "      <th>Length</th>\n",
       "      <th>Diameter</th>\n",
       "      <th>Height</th>\n",
       "      <th>Whole weight</th>\n",
       "      <th>Shucked weight</th>\n",
       "      <th>Viscera weight</th>\n",
       "      <th>Shell weight</th>\n",
       "      <th>Rings</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>0.455</td>\n",
       "      <td>0.365</td>\n",
       "      <td>0.095</td>\n",
       "      <td>0.5140</td>\n",
       "      <td>0.2245</td>\n",
       "      <td>0.1010</td>\n",
       "      <td>0.150</td>\n",
       "      <td>15</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0</td>\n",
       "      <td>0.350</td>\n",
       "      <td>0.265</td>\n",
       "      <td>0.090</td>\n",
       "      <td>0.2255</td>\n",
       "      <td>0.0995</td>\n",
       "      <td>0.0485</td>\n",
       "      <td>0.070</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1</td>\n",
       "      <td>0.530</td>\n",
       "      <td>0.420</td>\n",
       "      <td>0.135</td>\n",
       "      <td>0.6770</td>\n",
       "      <td>0.2565</td>\n",
       "      <td>0.1415</td>\n",
       "      <td>0.210</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0</td>\n",
       "      <td>0.440</td>\n",
       "      <td>0.365</td>\n",
       "      <td>0.125</td>\n",
       "      <td>0.5160</td>\n",
       "      <td>0.2155</td>\n",
       "      <td>0.1140</td>\n",
       "      <td>0.155</td>\n",
       "      <td>10</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2</td>\n",
       "      <td>0.330</td>\n",
       "      <td>0.255</td>\n",
       "      <td>0.080</td>\n",
       "      <td>0.2050</td>\n",
       "      <td>0.0895</td>\n",
       "      <td>0.0395</td>\n",
       "      <td>0.055</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Sex  Length  Diameter  Height  Whole weight  Shucked weight  \\\n",
       "0    0   0.455     0.365   0.095        0.5140          0.2245   \n",
       "1    0   0.350     0.265   0.090        0.2255          0.0995   \n",
       "2    1   0.530     0.420   0.135        0.6770          0.2565   \n",
       "3    0   0.440     0.365   0.125        0.5160          0.2155   \n",
       "4    2   0.330     0.255   0.080        0.2050          0.0895   \n",
       "\n",
       "   Viscera weight  Shell weight  Rings  \n",
       "0          0.1010         0.150     15  \n",
       "1          0.0485         0.070      7  \n",
       "2          0.1415         0.210      9  \n",
       "3          0.1140         0.155     10  \n",
       "4          0.0395         0.055      7  "
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = pd.read_csv('./abalone.csv')\n",
    "data['Sex'] = data['Sex'].map({'M':0, 'F':1, 'I':2})\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = data.drop(['Rings'], axis=1)\n",
    "y = data[['Rings']]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3132, 8) (3132, 1) (1045, 8) (1045, 1)\n"
     ]
    }
   ],
   "source": [
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)\n",
    "X_train, X_test, y_train, y_test = X_train.values, X_test.values, y_train.values, y_test.values\n",
    "print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义参数初始化函数\n",
    "def initialize(dims):\n",
    "    w = np.zeros((dims, 1))\n",
    "    b = 0\n",
    "    return w, b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义ridge损失函数\n",
    "def l2_loss(X, y, w, b, alpha):\n",
    "    num_train = X.shape[0]\n",
    "    num_feature = X.shape[1]\n",
    "    y_hat = np.dot(X, w) + b\n",
    "    loss = np.sum((y_hat-y)**2)/num_train + alpha*(np.sum(np.square(w)))\n",
    "    dw = np.dot(X.T, (y_hat-y)) /num_train + 2*alpha*w\n",
    "    db = np.sum((y_hat-y)) /num_train\n",
    "    return y_hat, loss, dw, db"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义训练过程\n",
    "def ridge_train(X, y, learning_rate=0.001, epochs=5000):\n",
    "    loss_list = []\n",
    "    w, b = initialize(X.shape[1])\n",
    "    for i in range(1, epochs):\n",
    "        y_hat, loss, dw, db = l2_loss(X, y, w, b, 0.1)\n",
    "        w += -learning_rate * dw\n",
    "        b += -learning_rate * db\n",
    "        loss_list.append(loss)\n",
    "        \n",
    "        if i % 100 == 0:\n",
    "            print('epoch %d loss %f' % (i, loss))\n",
    "        params = {\n",
    "            'w': w,\n",
    "            'b': b\n",
    "        }\n",
    "        grads = {\n",
    "            'dw': dw,\n",
    "            'db': db\n",
    "        }\n",
    "    return loss, loss_list, params, grads"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 100 loss 12.009008\n",
      "epoch 200 loss 10.278130\n",
      "epoch 300 loss 9.558112\n",
      "epoch 400 loss 9.105150\n",
      "epoch 500 loss 8.781454\n",
      "epoch 600 loss 8.540165\n",
      "epoch 700 loss 8.357414\n",
      "epoch 800 loss 8.218088\n",
      "epoch 900 loss 8.111632\n"
     ]
    }
   ],
   "source": [
    "# 执行训练示例\n",
    "loss, loss_list, params, grads = ridge_train(X_train, y_train, 0.01, 1000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'b': 6.811842405055238, 'w': array([[-0.17320731],\n",
       "        [ 1.1372835 ],\n",
       "        [ 0.92245614],\n",
       "        [ 0.35081766],\n",
       "        [ 1.92472894],\n",
       "        [ 0.50576768],\n",
       "        [ 0.38760524],\n",
       "        [ 0.76797801]])}"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 获取训练参数\n",
    "params"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 9.9532712 ],\n",
       "       [ 9.6663585 ],\n",
       "       [ 9.16269917],\n",
       "       [11.32027198],\n",
       "       [ 7.1519842 ]])"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 定义预测函数\n",
    "def predict(X, params):\n",
    "    w = params['w']\n",
    "    b = params['b']\n",
    "    \n",
    "    y_pred = np.dot(X, w) + b\n",
    "    return y_pred\n",
    "\n",
    "y_pred = predict(X_test, params)\n",
    "y_pred[:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[10],\n",
       "       [12],\n",
       "       [ 8],\n",
       "       [13],\n",
       "       [ 6]], dtype=int64)"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_test[:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 简单绘图\n",
    "import matplotlib.pyplot as plt\n",
    "f = X_test.dot(params['w']) + params['b']\n",
    "\n",
    "plt.scatter(range(X_test.shape[0]), y_test)\n",
    "plt.plot(f, color = 'darkorange')\n",
    "plt.xlabel('X')\n",
    "plt.ylabel('y')\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 训练过程中的损失下降\n",
    "plt.plot(loss_list, color = 'blue')\n",
    "plt.xlabel('epochs')\n",
    "plt.ylabel('loss')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sklearn Ridge intercept : [4.10453635]\n",
      "\n",
      "sklearn Ridge coefficients :\n",
      " [[ -0.45851193   2.18540968   8.15662431   6.93699459   6.94525282\n",
      "  -17.60842372  -6.76773076  10.92235029]]\n"
     ]
    }
   ],
   "source": [
    "# 导入线性模型模块\n",
    "from sklearn.linear_model import Ridge\n",
    "# 创建Ridge模型实例\n",
    "clf = Ridge(alpha=1.0)\n",
    "# 对训练集进行拟合\n",
    "clf.fit(X_train, y_train)\n",
    "# 打印模型相关系数\n",
    "print(\"sklearn Ridge intercept :\", clf.intercept_)\n",
    "print(\"\\nsklearn Ridge coefficients :\\n\", clf.coef_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 9.92562104],\n",
       "       [ 7.84003066],\n",
       "       [12.39512286],\n",
       "       [11.37856456],\n",
       "       [ 9.57795936]])"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "clf.predict(X_test)[:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
